# ImageThought.py
# This file is part of labyrinth
#
# Copyright (C) 2006 - Don Scorgie <DonScorgie@Blueyonder.co.uk>
#
# labyrinth is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# labyrinth is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with labyrinth; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA  02110-1301  USA
#

import gtk
import xml.dom.minidom as dom
import xml.dom
import gettext
_ = gettext.gettext

import BaseThought
import utils
import UndoManager

MODE_EDITING = 0
MODE_IMAGE = 1
MODE_DRAW = 2

UNDO_RESIZE = 0

class ImageThought (BaseThought.ResizableThought):
	def __init__ (self, coords, pango_context, thought_number, save, undo, loading):
		super (ImageThought, self).__init__(save, "image_thought", undo)

		self.identity = thought_number
		margin = utils.margin_required (utils.STYLE_NORMAL)
		self.want_move = False
		if coords:
			self.ul = (coords[0]-margin[0], coords[1] - margin[1])
			self.pic_location = coords
		else:
			self.ul = None
		self.button_press = False

		if not loading:
			self.all_okay = self.open_image ()
		else:
			self.all_okay = True


	def open_image (self, filename = None):
		# Present a dialog for the user to choose an image here
		if not filename:
			fil = gtk.FileFilter ()
			fil.set_name("Images")
			fil.add_pixbuf_formats ()
			dialog = gtk.FileChooserDialog (_("Choose image to insert"), None, gtk.FILE_CHOOSER_ACTION_OPEN, \
			                         (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
			dialog.add_filter (fil)
			res = dialog.run ()
			dialog.hide ()
			if res != gtk.RESPONSE_OK:
				return False
			else:
				fname = dialog.get_filename()
		else:
			fname = filename
		self.filename = fname
		try:
			self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname)
		except:
			return False
		if not filename:
			self.width = self.orig_pic.get_width ()
			self.height = self.orig_pic.get_height ()
			margin = utils.margin_required (utils.STYLE_NORMAL)

			self.lr = (self.pic_location[0]+self.width+margin[2], self.pic_location[1]+self.height+margin[3])
			self.pic = self.orig_pic
		self.text = fname[fname.rfind('/')+1:fname.rfind('.')]
		return True

	def draw (self, context):
		utils.draw_thought_outline (context, self.ul, self.lr, self.am_selected, self.am_primary, utils.STYLE_NORMAL)

		if self.pic:
			context.set_source_pixbuf (self.pic, self.pic_location[0], self.pic_location[1])
			context.rectangle (self.pic_location[0], self.pic_location[1], self.width, self.height)
			context.fill ()
		context.set_source_rgb (0,0,0)

	def export (self, context, move_x, move_y):
		utils.export_thought_outline (context, self.ul, self.lr, self.am_selected, self.am_primary, utils.STYLE_NORMAL,
									  (move_x, move_y))

		if self.pic:
			context.set_source_pixbuf (self.pic, self.pic_location[0]+move_x, self.pic_location[1]+move_y)
			context.rectangle (self.pic_location[0]+move_x, self.pic_location[1]+move_y,
							   self.width, self.height)
			context.fill ()
		context.set_source_rgb (0,0,0)

	def want_motion (self):
		return self.want_move

	def recalc_edges (self):
		margin = utils.margin_required (utils.STYLE_NORMAL)
		self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1])
		self.lr = (self.pic_location[0]+self.width+margin[2], self.pic_location[1]+self.height+margin[3])

	def undo_resize (self, action, mode):
		self.undo.block ()
		if mode == UndoManager.UNDO:
			choose = 0
		else:
			choose = 1
		self.ul = action.args[choose][0]
		self.width = action.args[choose][1]
		self.height = action.args[choose][2]
		self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_HYPER)
		self.recalc_edges ()
		self.emit ("update_links")
		self.emit ("update_view")
		self.undo.unblock ()

	def process_button_down (self, event, mode):
		modifiers = gtk.accelerator_get_default_mod_mask ()
		self.button_down = True
		if event.button == 1:
			if event.type == gtk.gdk.BUTTON_PRESS:
				self.emit ("select_thought", event.state & modifiers)
				self.emit ("update_view")
			if mode == MODE_EDITING and self.resizing != self.RESIZE_NONE:
				self.orig_size = (self.ul, self.width, self.height)
				self.want_move = True
				return True
		elif event.button == 3:
			self.emit ("popup_requested", (event.x, event.y), 1)
		self.emit ("update_view")


	def process_button_release (self, event, unending_link, mode):
		self.button_down = False
		if unending_link:
			unending_link.set_child (self)
			self.emit ("claim_unending_link")
		if self.orig_pic:
			self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_HYPER)
		self.emit ("update_view")
		if self.want_move:
			self.undo.add_undo (UndoManager.UndoAction (self, UNDO_RESIZE, self.undo_resize, \
														self.orig_size, (self.ul, self.width, self.height)))
			self.want_move = False

	def handle_motion (self, event, mode):
		if self.resizing == self.RESIZE_NONE or not self.want_move or not event.state & gtk.gdk.BUTTON1_MASK:
			if not event.state & gtk.gdk.BUTTON1_MASK:
				return False
			elif mode == MODE_EDITING:
				self.emit ("create_link", \
				 (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.), self.ul[1]-((self.ul[1]-self.lr[1]) / 2.)))
			return True
		diffx = event.x - self.motion_coords[0]
		diffy = event.y - self.motion_coords[1]
		tmp = self.motion_coords
		self.motion_coords = (event.x,event.y)
		if self.resizing == self.RESIZE_LEFT:
			if self.width - diffx < 10:
				self.motion_coords = tmp
				return True
			self.ul = (self.ul[0]+diffx, self.ul[1])
			self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1])
			self.width -= diffx
		elif self.resizing == self.RESIZE_RIGHT:
			if self.width + diffx < 10:
				self.motion_coords = tmp
				return True
			self.lr = (self.lr[0]+diffx, self.lr[1])
			self.width += diffx
		elif self.resizing == self.RESIZE_TOP:
			if self.height - diffy < 10:
				self.motion_coords = tmp
				return True
			self.ul = (self.ul[0], self.ul[1]+diffy)
			self.pic_location = (self.pic_location[0], self.pic_location[1]+diffy)
			self.height -= diffy
		elif self.resizing == self.RESIZE_BOTTOM:
			if self.height + diffy < 10:
				self.motion_coords = tmp
				return True
			self.lr = (self.lr[0], self.lr[1]+diffy)
			self.height += diffy
		elif self.resizing == self.RESIZE_UL:
			if self.height - diffy < 10 or self.width - diffx < 10:
				self.motion_coords = tmp
				return True
			self.ul = (self.ul[0]+diffx, self.ul[1]+diffy)
			self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1]+diffy)
			self.width -= diffx
			self.height -= diffy
		elif self.resizing == self.RESIZE_UR:
			if self.height - diffy < 10 or self.width + diffx < 10:
				self.motion_coords = tmp
				return True
			self.ul = (self.ul[0], self.ul[1]+diffy)
			self.lr = (self.lr[0]+diffx, self.lr[1])
			self.pic_location = (self.pic_location[0], self.pic_location[1]+diffy)
			self.width += diffx
			self.height -= diffy
		elif self.resizing == self.RESIZE_LL:
			if self.height + diffy < 10 or self.width - diffx < 10:
				self.motion_coords = tmp
				return True
			self.ul = (self.ul[0]+diffx, self.ul[1])
			self.lr = (self.lr[0], self.lr[1]+diffy)
			self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1])
			self.width -= diffx
			self.height += diffy
		elif self.resizing == self.RESIZE_LR:
			if self.height + diffy < 10:
				self.motion_coords = tmp
				return True
			if self.width + diffx < 10:
				self.motion_coords = tmp
				return True
			self.lr = (self.lr[0]+diffx, self.lr[1]+diffy)
			self.width += diffx
			self.height += diffy
		if self.orig_pic:
			self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_NEAREST)
		self.emit ("update_links")
		self.emit ("update_view")
		return True

	def update_save (self):
		text = self.extended_buffer.get_text ()
		if text:
			self.extended_element.replaceWholeText (text)
		else:
			self.extended_element.replaceWholeText ("LABYRINTH_AUTOGEN_TEXT_REMOVE")
		self.element.setAttribute ("ul-coords", str(self.ul))
		self.element.setAttribute ("lr-coords", str(self.lr))
		self.element.setAttribute ("identity", str(self.identity))
		self.element.setAttribute ("file", str(self.filename))
		self.element.setAttribute ("image_width", str(self.width))
		self.element.setAttribute ("image_height", str(self.height))
		if self.am_selected:
				self.element.setAttribute ("current_root", "true")
		else:
			try:
				self.element.removeAttribute ("current_root")
			except xml.dom.NotFoundErr:
				pass
		if self.am_primary:
			self.element.setAttribute ("primary_root", "true")
		else:
			try:
				self.element.removeAttribute ("primary_root")
			except xml.dom.NotFoundErr:
				pass
		return

	def load (self, node):
		tmp = node.getAttribute ("ul-coords")
		self.ul = utils.parse_coords (tmp)
		tmp = node.getAttribute ("lr-coords")
		self.lr = utils.parse_coords (tmp)
		self.filename = node.getAttribute ("file")
		self.identity = int (node.getAttribute ("identity"))
		self.width = float(node.getAttribute ("image_width"))
		self.height = float(node.getAttribute ("image_height"))
		if node.hasAttribute ("current_root"):
			self.am_selected = True
		else:
			self.am_selected = False
		if node.hasAttribute ("primary_root"):
			self.am_primary = True
		else:
			self.am_primary = False

		for n in node.childNodes:
			if n.nodeName == "Extended":
				for m in n.childNodes:
					if m.nodeType == m.TEXT_NODE:
						text = m.data
						if text != "LABYRINTH_AUTOGEN_TEXT_REMOVE":
							self.extended_buffer.set_text (text)
			else:
				print "Unknown: "+n.nodeName
		margin = utils.margin_required (utils.STYLE_NORMAL)
		self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1])
		self.okay = self.open_image (self.filename)
		self.lr = (self.pic_location[0]+self.width+margin[2], self.pic_location[1]+self.height+margin[3])
		if not self.okay:
			dialog = gtk.MessageDialog (None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
										gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE,
										_("Error loading file"))
			dialog.format_secondary_text (_("%s could not be found.  Associated thought will be empty."%self.filename))
			dialog.run ()
			dialog.hide ()
			self.pic = None
			self.orig_pic = None
		else:
			self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_HYPER)
		return
